package com.bjsxt.pool;

import java.util.concurrent.*;

public class SumTask extends RecursiveTask<Long> {

    int startNum;
    int endNum;
    int step = 10000;

    public SumTask(int startNum, int endNum) {
        this.startNum = startNum;
        this.endNum = endNum;
    }

    @Override
    protected Long compute() {

        //定义结果变量
        long sum = 0;

        //计算结果
        if (endNum - startNum <= step) {
            for (int i = startNum; i <= endNum; i++) {
                sum += i;
            }
        } else {
            //1.分解成两个子任务
            int middle = (startNum + endNum) / 2;
            SumTask leftTask = new SumTask(startNum, middle);
            SumTask rightTask = new SumTask(middle + 1, endNum);

            //2.提交子任务
            leftTask.fork();
            rightTask.fork();

            //3.等待子任务结果，并合并结果
            long leftSum = leftTask.join();
            long rightSum = rightTask.join();
            sum = leftSum + rightSum;
        }

        //返回结果
        return sum;
    }

    public static void main(String[] args) throws Exception {

        //1.使用循环求和
        //假设计算机为4核，该方法只使用了1个核
        long sum = 0;
        int n = 1000000000;
        long startTime = System.currentTimeMillis();
        for (int i = 1; i <= n; i++) {
            sum += i;
        }
        long endTime = System.currentTimeMillis();
        System.out.println(sum);
        System.out.println("循环求和耗时：" + (endTime - startTime) + "ms");

        System.out.println("===========================================");

        //2.使用ForkJoin框架求和
        //假设计算机为4核，该方法能充分使用4个核
        //类似Lock的多个等待队列？
        startTime = System.currentTimeMillis();

        //2.1.创建一个ForkJoin线程池
        ForkJoinPool pool = new ForkJoinPool();

        //2.2.给出一个求和任务
        RecursiveTask task = new SumTask(1, n);

        //2.3.将任务交给线程池
        Future<Long> future = pool.submit(task);

        //2.4.获取结果并输出
        long result = future.get();
        System.out.println(result);

        endTime = System.currentTimeMillis();
        System.out.println("ForkJoin框架求和耗时：" + (endTime - startTime) + "ms");

        //2.5.关闭线程池
        pool.shutdown();

    }

}
